home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / Boxer / PalmBoxer / unzip.c < prev   
Encoding:
C/C++ Source or Header  |  2000-06-23  |  10.3 KB  |  395 lines

  1. #define IGNORE_STDIO_STUBS
  2. #define __string_h
  3.  
  4. #ifdef OLDGCC
  5.  
  6. #include <Common.h>
  7. #include <System/SysAll.h>
  8. #include <UI/UIAll.h>
  9. #include <Unix/sys_types.h>
  10.  
  11. #else
  12.  
  13. #include <PalmOS.h>
  14. #include <PalmCompatibility.h>
  15. #include <Unix/sys_types.h>
  16.  
  17. #endif
  18.  
  19. #include "stringil.h"
  20. #include "stdio2.h"
  21. #include "zlib.h"
  22.  
  23. #ifdef __PALMOS_TRAPS__
  24. Err errno;
  25. #endif
  26.  
  27. int fgetc(FILE * fp)
  28. {
  29.   unsigned char lastchr;
  30.   if (1 == fread(&lastchr, 1, 1, fp))
  31.     return lastchr;
  32.   else
  33.     return -1;
  34. }
  35.  
  36. FILE *fopen(char *name, char *mode)
  37. {
  38.   // Modes need lots of work
  39.   return FileOpen(0, name, 'DATA', 'NZIP',
  40.                   (*mode == 'r' ? fileModeReadOnly : fileModeReadWrite)
  41.                   | fileModeAnyTypeCreator, NULL);
  42. }
  43.  
  44. #define STORED            0     /* compression methods */
  45. #define DEFLATED          8
  46.  
  47. #  define CRCVAL_INITIAL  0L
  48.  
  49. /* PKZIP header definitions */
  50. #define ZIPMAG 0x4b50           /* two-byte zip lead-in */
  51. #define LOCREM 0x0403           /* remaining two bytes in zip signature */
  52. #define LOCSIG 0x04034b50L      /* full signature */
  53. #define LOCFLG 4                /* offset of bit flag */
  54. #define  CRPFLG 1               /*  bit for encrypted entry */
  55. #define  EXTFLG 8               /*  bit for extended local header */
  56. #define LOCHOW 6                /* offset of compression method */
  57. #define LOCTIM 8                /* file mod time (for decryption) */
  58. #define LOCCRC 12               /* offset of crc */
  59. #define LOCSIZ 16               /* offset of compressed size */
  60. #define LOCLEN 20               /* offset of uncompressed length */
  61. #define LOCFIL 24               /* offset of file name field length */
  62. #define LOCEXT 26               /* offset of extra field length */
  63. #define LOCHDR 28               /* size of local header, including LOCREM */
  64. #define EXTHDR 16               /* size of extended local header, inc sig */
  65.  
  66. /* GZIP header definitions */
  67. #define GZPMAG 0x8b1f           /* two-byte gzip lead-in */
  68. #define GZPHOW 0                /* offset of method number */
  69. #define GZPFLG 1                /* offset of gzip flags */
  70. #define  GZPMUL 2               /* bit for multiple-part gzip file */
  71. #define  GZPISX 4               /* bit for extra field present */
  72. #define  GZPISF 8               /* bit for filename present */
  73. #define  GZPISC 16              /* bit for comment present */
  74. #define  GZPISE 32              /* bit for encryption */
  75. #define GZPTIM 2                /* offset of Unix file modification time */
  76. #define GZPEXF 6                /* offset of extra flags */
  77. #define GZPCOS 7                /* offset of operating system compressed on */
  78. #define GZPHDR 8                /* length of minimal gzip header */
  79.  
  80. /* Macros for getting two-byte and four-byte header values */
  81. #define SH(p) ((unsigned short int)(unsigned char)((p)[0]) | ((unsigned short int)(unsigned char)((p)[1]) << 8))
  82. #define LG(p) ((unsigned long)(SH(p)) | ((unsigned long)(SH((p)+2)) << 16))
  83.  
  84. /* Globals */
  85.  
  86. #define BSIZ 128
  87.  
  88. #define err(n, m) {fprintf(stderr,m );return n;}
  89.  
  90. int unzipdir(FILE * infile, char *dir, long int *loc)
  91. {
  92.   int encrypted;                /* flag to turn on decryption */
  93.   unsigned long total;
  94.   unsigned short int n;
  95.   unsigned char h[LOCHDR];      /* first local header (GZPHDR < LOCHDR) */
  96.   unsigned char ibuf[BSIZ];
  97.   char *c;
  98.   int max;
  99.  
  100.   *dir = 0;
  101.   dir[1] = 0;
  102.   max = 0;
  103.  
  104.   fseek(infile, 0, SEEK_SET);
  105.  
  106.   /* read ZIPal header, check validity */
  107.   n = fgetc(infile);
  108.   if (n > 255 || feof(infile))
  109.     return 0;
  110.   n |= fgetc(infile) << 8;
  111.  
  112.   if (n != ZIPMAG)
  113.     return 0;
  114.  
  115.   fseek(infile, 0, SEEK_SET);
  116.  
  117.   for (;;) {
  118.     /* read local header, check validity, and skip name and extra fields */
  119.     n = fgetc(infile);
  120.     if (n > 255 || feof(infile))
  121.       return max;
  122.  
  123.     n |= fgetc(infile) << 8;
  124.  
  125.     if (n != ZIPMAG)
  126.       return max;
  127.  
  128.     *loc++ = ftell(infile) - 2L;
  129.  
  130.     fread((char *) h, 1, LOCHDR, infile);
  131.     if (SH(h) == 0x0201)
  132.       return max;               // start of central directory
  133.     if (SH(h) != LOCREM)
  134.       err(3, "invalid zipfile");
  135.  
  136.     /* FILENAME */
  137.     ibuf[SH(h + LOCFIL)] = 0;
  138.     fread(ibuf, 1, SH(h + LOCFIL), infile);
  139.  
  140.     for (n = SH(h + LOCEXT); n--;)
  141.       fgetc(infile);
  142.     encrypted = h[LOCFLG] & CRPFLG;
  143.  
  144.     total = LG(h + LOCSIZ);
  145.     c = ibuf;
  146.     while (*c) {
  147.       if (*c <= ' ' || *c >= 0x7f)
  148.         *c = '_';
  149.       c++;
  150.     }
  151.     c = ibuf;
  152.     if (strlen(ibuf) > 32)
  153.       c += strlen(ibuf) - 32;
  154.  
  155.     strcpy(dir,c);
  156.     dir += strlen(c)+1;
  157.     *dir = 0;
  158.  
  159.     /* if entry encrypted, decrypt and validate encryption header */
  160.     if (encrypted)
  161.       err(3, "cannot decrypt entry (need to recompile with full crypt.c)");
  162.  
  163.     fseek(infile, total, SEEK_CUR);
  164.  
  165.     /* if extended header, get it */
  166.     if ((h[LOCFLG] & EXTFLG) &&
  167.     fread((char *) h + LOCCRC - 4, 1, EXTHDR, infile) != EXTHDR)
  168.       err(3, "zipfile ended prematurely");
  169.     
  170.     max++;
  171.  
  172.   }
  173.  
  174. }
  175.  
  176.  
  177.  
  178.  
  179. int unzip(FILE * infile, long int loc)
  180. {
  181.   FILE *outfile;
  182.   unsigned long crc32val;
  183.   unsigned long outsiz;         /* total bytes written to out */
  184.   int encrypted;                /* flag to turn on decryption */
  185.   unsigned long total, itot;
  186.   unsigned short int n;
  187.   unsigned char h[LOCHDR];      /* first local header (GZPHDR < LOCHDR) */
  188.   int k = 0, got;
  189.   unsigned char ibuf[BSIZ], obuf[BSIZ];
  190.   z_stream pgpz;
  191.   int gz = 0;                   /* true if gzip format */
  192.   char *c;
  193.   RectangleType r;
  194.  
  195.   fseek(infile, 0, SEEK_SET);
  196.   /* read ZIPal header, check validity */
  197.   n = fgetc(infile);
  198.   if (n > 255 || feof(infile))
  199.     return 0;
  200.   n |= fgetc(infile) << 8;
  201.  
  202.   if (n != ZIPMAG && n != GZPMAG)
  203.     return -1;
  204.  
  205.   if( loc == -1 ) {
  206.     fseek(infile, 0, SEEK_SET);
  207.     FileControl(fileOpDestructiveReadMode, infile, NULL, NULL);
  208.   }
  209.   else
  210.     fseek(infile, loc, SEEK_SET);
  211.  
  212.   for (;;) {
  213.  
  214.     /* read local header, check validity, and skip name and extra fields */
  215.     n = fgetc(infile);
  216.     if (n > 255 || feof(infile))
  217.       return 0;
  218.  
  219.     n |= fgetc(infile) << 8;
  220.  
  221.     r.topLeft.x = 0, r.topLeft.y = 15, r.extent.x = 160, r.extent.y = 30;
  222.     WinEraseRectangle(&r, 0);
  223.  
  224.     if (n == ZIPMAG) {
  225.       fread((char *) h, 1, LOCHDR, infile);
  226.       if (SH(h) == 0x0201)
  227.         return 0;               // start of central directory
  228.       if (SH(h) != LOCREM)
  229.         err(3, "invalid zipfile");
  230.       if (SH(h + LOCHOW) != STORED && SH(h + LOCHOW) != DEFLATED)
  231.         err(3, "entry not deflated or stored--cannot unpack");
  232.  
  233.       /* FILENAME */
  234.       ibuf[SH(h + LOCFIL)] = 0;
  235.       fread(ibuf, 1, SH(h + LOCFIL), infile);
  236.  
  237.       for (n = SH(h + LOCEXT); n--;)
  238.         gz = fgetc(infile);
  239.       gz = 0;
  240.       encrypted = h[LOCFLG] & CRPFLG;
  241.     }
  242.  
  243.     else if (n == GZPMAG) {
  244.       fread((char *) h, 1, GZPHDR, infile);
  245.       if ((h[GZPHOW] != DEFLATED) || (h[GZPFLG] & GZPMUL))
  246.         err(3, "cannot handle this gzip file");
  247.  
  248.       if (h[GZPFLG] & GZPISX) {
  249.         n = fgetc(infile);
  250.         n |= fgetc(infile) << 8;
  251.         fread(ibuf, 1, n, infile);
  252.       }
  253.  
  254.       if (h[GZPFLG] & GZPISF) {
  255.         c = ibuf;
  256.         while ((*c++ = fgetc(infile)) != 0);
  257.       } else {
  258.         strcpy(ibuf, "gzipun-");
  259.         StrIToA(&ibuf[7], TimGetSeconds());
  260.     strcat(ibuf,".tar");
  261.       }
  262.  
  263.       if (h[GZPFLG] & GZPISC)
  264.         while ((gz = fgetc(infile)) != 0 && gz != -1);
  265.  
  266.       gz = 1;
  267.       encrypted = h[GZPFLG] & GZPISE;
  268.     }
  269.  
  270.     else
  271.       return 1;
  272.  
  273.     total = gz ? 0x7fffffff : LG(h + LOCSIZ);
  274.     if (!total) {
  275.       if( loc == -1 )
  276.     continue;
  277.       else
  278.     return -1;
  279.     }
  280.  
  281.     /* fix filename and open for write */
  282.     c = ibuf;
  283.     while (*c) {
  284.       if (*c <= ' ' || *c >= 0x7f)
  285.         *c = '_';
  286.       c++;
  287.     }
  288.     c = ibuf;
  289.     if (strlen(ibuf) > 32)
  290.       c += strlen(ibuf) - 32;
  291.     outfile = fopen(c, "w");
  292.     WinDrawChars(c, strlen(c), 0, 15);
  293.  
  294.  
  295.     /* if entry encrypted, decrypt and validate encryption header */
  296.     if (encrypted)
  297.       err(3, "cannot decrypt entry (need to recompile with full crypt.c)");
  298.  
  299.     itot = total;
  300.     outsiz = 0L;
  301.     crc32val = CRCVAL_INITIAL;
  302.  
  303.     r.topLeft.y = 30, r.extent.y = 15;
  304.  
  305.     /* decompress */
  306.     if (gz || h[LOCHOW]) {      /* deflated entry */
  307.       outsiz = 0;
  308.       memset(&pgpz, 0, sizeof(pgpz));
  309.       inflateInit2(&pgpz, -15);
  310.  
  311.       do {
  312.         while (total && !feof(infile)) {
  313.  
  314.           if (0 > (got = fread(ibuf, 1, total > BSIZ ? BSIZ : total, infile)))
  315.             break;
  316.  
  317.           total -= got;
  318.           if (gz)
  319.             WinDrawChars( gz++ & 1 ? "\\" : "/" , 1, 0, 30);
  320.           else {
  321.             r.extent.x = 160 - (160 * total / itot);
  322.             WinDrawRectangle(&r, 0);
  323.           }
  324.           pgpz.next_in = ibuf;
  325.           pgpz.avail_in = got;
  326.           while (pgpz.avail_in || !total || feof(infile)) {
  327.             pgpz.next_out = obuf;
  328.             pgpz.avail_out = BSIZ;
  329.             k = inflate(&pgpz, !total || !feof(infile) ? 0 : Z_FINISH);
  330.             fwrite(obuf, 1, BSIZ - pgpz.avail_out, outfile);
  331.  
  332.             outsiz += BSIZ - pgpz.avail_out;
  333.             crc32val = crc32(crc32val, obuf, BSIZ - pgpz.avail_out);
  334.  
  335.             if (k == Z_BUF_ERROR && pgpz.avail_out != BSIZ
  336.                 && (total || feof(infile))) continue; /* for undoc zlib */
  337.             if (k != Z_OK)
  338.               break;
  339.           }
  340.         }
  341.       } while (total && !feof(infile));
  342.       inflateEnd(&pgpz);
  343.  
  344.       //error status:       (k == Z_STREAM_END);
  345.     }
  346.  
  347.  
  348.     else {                      /* stored entry */
  349.  
  350.       got = LG(h + LOCLEN);
  351.       if (got != LG(h + LOCSIZ))
  352.         err(4, "invalid compressed data--length mismatch");
  353.  
  354.       total = got;
  355.       while (total) {
  356.         got = fread(ibuf, 1, total > BSIZ ? BSIZ : total, infile);
  357.         outsiz += got;
  358.         total -= got;
  359.         r.extent.x = 160 - (160 * total / itot);
  360.         WinDrawRectangle(&r, 0);
  361.         crc32val = crc32(crc32val, ibuf, got);
  362.  
  363.         fwrite(ibuf, 1, got, outfile);
  364.       }
  365.     }
  366.     fclose(outfile);
  367.  
  368.     /* if extended header, get it */
  369.     if (gz) {
  370.       if (pgpz.avail_in < 8)
  371.         err(3, "gzip ended prematurely");
  372.       memcpy((char *) h + LOCCRC, pgpz.next_in, 8);
  373.  
  374.       break;                    //THIS DOESN'T WORK HERE
  375.     }
  376.       else
  377.       if ((h[LOCFLG] & EXTFLG) &&
  378.           fread((char *) h + LOCCRC - 4, 1, EXTHDR, infile) != EXTHDR)
  379.         err(3, "zipfile ended prematurely");
  380.  
  381.     /* validate decompression */
  382.     if (LG(h + LOCCRC) != crc32val)
  383.       err(4, "invalid compressed data--crc error");
  384.  
  385.     if (LG((gz ? (h + LOCSIZ) : (h + LOCLEN))) != outsiz)
  386.       err(4, "invalid compressed data--length error");
  387.  
  388.       if( loc != -1 )
  389.     break;
  390.  
  391.   }
  392.  
  393.   return 0;
  394. }
  395.